package com.foogui.primary.readwrite;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class CopyOnWriteMapDemo {
    public static final CopyOnWriteMap<String, Boolean> copyOnWriteMap = new CopyOnWriteMap<>(1000);

    public boolean isBlackList(String id) {
        return copyOnWriteMap.get(id) != null;
    }

    // 添加黑名单
    public static void addBlackList(String id) {
        copyOnWriteMap.put(id, Boolean.TRUE);
    }
    /**
     * 批量添加黑名单
     * (使用批量添加。因为每次添加，容器每次都会进行复制，所以减少添加次数，可以减少容器的复制次数。
     * 如使用上面代码里的addBlackList方法)
     *
     * @param ids
     */
    public static void addBlackList(Map<String, Boolean> ids) {
        copyOnWriteMap.putAll(ids);
    }

    private static class CopyOnWriteMap<K, V> implements Map<K, V>, Cloneable {
        private volatile Map<K, V> map;

        public CopyOnWriteMap(int capacity) {
            this.map = new HashMap<>(capacity);
        }

        @Override
        public int size() {
            return map.size();
        }

        @Override
        public boolean isEmpty() {
            return map.size() == 0;
        }

        @Override
        public boolean containsKey(Object key) {
            return map.containsKey(key);
        }

        @Override
        public boolean containsValue(Object value) {
            return map.containsValue(value);
        }

        @Override
        public V get(Object key) {
            return map.get(key);
        }

        @Override
        public V put(K key, V value) {
            synchronized (this) {
                HashMap<K, V> newMap = new HashMap<>(map);
                V val = newMap.put(key, value);
                map = newMap;
                return val;
            }
        }

        @Override
        public V remove(Object key) {
            synchronized (this) {
                HashMap<K, V> newMap = new HashMap<>(map);
                V val = newMap.remove(key);
                map = newMap;
                return val;
            }
        }

        @Override
        public void putAll(Map<? extends K, ? extends V> m) {
            synchronized (this) {
                HashMap<K, V> newMap = new HashMap<>(map);
                newMap.putAll(map);
                map = newMap;
            }
        }

        @Override
        public void clear() {
            synchronized (this) {
                map.clear();
            }
        }

        @Override
        public Set<K> keySet() {
            return null;
        }

        @Override
        public Collection<V> values() {
            return null;
        }

        @Override
        public Set<Entry<K, V>> entrySet() {
            return null;
        }
    }


}
